#pragma once

#define GLM_ENABLE_EXPERIMENTAL
#include "glm/gtx/string_cast.hpp"

#include "spdlog/spdlog.h"
#include "spdlog/fmt/ostr.h"

namespace Cogs {
	class Log {
	public:
		static void Init();
		inline static std::shared_ptr<spdlog::logger>& GetCoreLogger() { return s_CoreLogger; }
		inline static std::shared_ptr<spdlog::logger>& GetClientLogger() { return s_ClientLogger; }
	private:
		static std::shared_ptr<spdlog::logger> s_CoreLogger;
		static std::shared_ptr<spdlog::logger> s_ClientLogger;
	};

	template<typename OStream,glm::length_t L,typename T,glm::qualifier Q>
	inline OStream& operator <<(OStream& os, const glm::vec<L, T, Q>& vector) {
		return os << glm::to_string(vector);
	}

	template<typename OStream,glm::length_t C,glm::length_t R,typename T, glm::qualifier Q>
	inline OStream& operator<<(OStream& os, const glm::mat<C, R, T, Q>& matrix) {
		return os << glm::to_string(matrix);
	}

	template<typename OStream,typename T,glm::qualifier Q>
	inline OStream& operator<<(OStream& os, const glm::qua<T, Q>& quaternio) {
		return os << glm::to_string(quaternio);
	}
}

//Core log macros
#define COGS_CORE_TRACE(...)	Cogs::Log::GetCoreLogger()->trace(__VA_ARGS__)
#define COGS_CORE_Info(...)		Cogs::Log::GetCoreLogger()->info(__VA_ARGS__)
#define COGS_CORE_Warn(...)		Cogs::Log::GetCoreLogger()->warn(__VA_ARGS__)
#define COGS_CORE_Error(...)	Cogs::Log::GetCoreLogger()->error(__VA_ARGS__)
#define COGS_CORE_CRITICAL(...)	Cogs::Log::GetCoreLogger()->critical(__VA_ARGS__)

//Client log macros
#define COGS_CLIENT_TRACE(...)		Cogs::Log::GetClientLogger()->trace(__VA_ARGS__)
#define COGS_CLIENT_Info(...)		Cogs::Log::GetClientLogger()->info(__VA_ARGS__)
#define COGS_CLIENT_Warn(...)		Cogs::Log::GetClientLogger()->warn(__VA_ARGS__)
#define COGS_CLIENT_Error(...)		Cogs::Log::GetClientLogger()->error(__VA_ARGS__)
#define COGS_CLIENT_CRITICAL(...)	Cogs::Log::GetClientLogger()->critical(__VA_ARGS__)
